﻿using System.Collections;
using System.Dynamic;
using Basic.FormCollect;
using Basic.FormModel;
using Basic.FormModel.Form;
using Basic.FormModel.FormViewCol;
using Basic.FormRemoteModel;
using Basic.FormRemoteModel.QueryInter.Model;
using Basic.UserFormService.Interface;
using WeDonekRpc.Helper;

namespace Basic.UserFormService.lmpl
{
    internal class FormViewValueService : IFormViewValueService
    {
        private static readonly string[] _Cols = new string[] { ConstDic.LinkType, ConstDic.LinkPk };
        private readonly IAgentFormCollect _Record;
        private readonly IFormViewColCollect _ViewCol;
        private readonly IQueryColumnCollect _Column;

        public FormViewValueService ( IAgentFormCollect record,
            IFormViewColCollect viewCol,
            IQueryColumnCollect column )
        {
            this._Record = record;
            this._ViewCol = viewCol;
            this._Column = column;
        }

        public FormVal GetValue ( FormBase form, FormValGetArg arg )
        {
            FormVal val = new FormVal
            {
                IsNull = true
            };
            FormViewColDto select = this._ViewCol.Get<FormViewColDto>(arg.ColumnId);
            if ( select == null )
            {
                return val;
            }
            else if ( this._ViewCol.CheckIsExists(form.Id, _Cols) )
            {
                dynamic value = this._Record.Get(form.TableName, arg.LinkType, arg.LinkPK, select.Alias);
                return this._GetRowVal(value, select);
            }
            else
            {
                return this._GetRowList(select, form.TableName);
            }
        }
        private FormVal _GetRowVal ( dynamic row, FormViewColDto col )
        {
            dynamic value = row[col.Alias];
            FormVal val = new FormVal
            {
                DataType = col.GetDataType(),
                IsNull = value == null,
                FuncType = col.ColFuncType.ToDataFuncType(),
                DicId = col.DictId
            };
            if ( val.IsNull )
            {
                return val;
            }
            else if ( val.DataType == FormRecordDataType.Array )
            {
                val.IsNull = false;
                val.DataType = FormRecordDataType.Array;
                val.Vals = ( (string)value ).SplitDel();
            }
            else if ( val.DataType == FormRecordDataType.String )
            {
                val.StrVal = (string)value;
            }
            else if ( val.DataType == FormRecordDataType.Bool )
            {
                val.BoolVal = (bool)value;
            }
            else if ( val.DataType == FormRecordDataType.Long || val.DataType == FormRecordDataType.Time )
            {
                val.LongVal = (long)value;
            }
            else if ( val.DataType == FormRecordDataType.Number )
            {
                val.NumVal = (decimal)value;
                val.NumStep = col.Precision;
            }
            else if ( val.DataType == FormRecordDataType.Date || val.DataType == FormRecordDataType.DateTime )
            {
                val.LongVal = ( (DateTime)value ).ToLong();
            }
            if ( col.ColumnSet != null && col.FuncType == PageFuncType.None )
            {
                if ( val.DataType == FormRecordDataType.Bool )
                {
                    val.ActivateText = col.ColumnSet.TryGetValue("ActiveText", out object t) ? t.ToString() : null;
                    val.InactiveText = col.ColumnSet.TryGetValue("InactiveText", out t) ? t.ToString() : null;
                }
                else if ( val.FuncType == DataFuncType.选项值 && col.ColumnSet.TryGetValue("Items", out object obj) && obj != null )
                {
                    IList list = obj as IList;
                    val.Items = new Dictionary<string, string>();
                    foreach ( IDictionary<string, object> i in list )
                    {
                        object k = i["value"];
                        val.Items.Add(Convert.ToString(i["text"]), k == null ? null : Convert.ToString(k));
                    }
                }
                else if ( val.FuncType == DataFuncType.上传的附件 && col.ColumnSet.TryGetValue("DirKey", out obj) && obj != null )
                {
                    val.DirKey = Convert.ToString(obj);
                }
            }
            return val;
        }

        private FormVal _Format ( object[] vals, FormViewColDto col )
        {
            FormVal val = new FormVal
            {
                DataType = FormRecordDataType.ListItem,
                IsNull = vals.IsNull(),
                FuncType = col.ColFuncType.ToDataFuncType(),
                DicId = col.DictId
            };
            if ( val.IsNull )
            {
                return val;
            }
            FormRecordDataType dataType = col.GetDataType();
            if ( dataType == FormRecordDataType.Array )
            {
                val.ListItem = new FormListItem
                {
                    DataType = FormRecordDataType.Array,
                    Vals = vals.ConvertAll(c => ( (string)c ).SplitDel())
                };
                val.ListItem.Len = val.ListItem.Vals.Length;
            }
            else if ( dataType == FormRecordDataType.Long ||
               dataType == FormRecordDataType.Time )
            {
                val.ListItem = new FormListItem
                {
                    DataType = FormRecordDataType.Long,
                    LongVal = vals.ConvertAll<object, long?>(a => (long)a)
                };
                val.ListItem.Len = val.ListItem.LongVal.Length;
            }
            else if ( dataType == FormRecordDataType.DateTime ||
                dataType == FormRecordDataType.Date )
            {
                val.ListItem = new FormListItem
                {
                    DataType = FormRecordDataType.Long,
                    LongVal = vals.ConvertAll<object, long?>(a =>
                    {
                        DateTime? time = (DateTime?)a;
                        return time.HasValue ? time.Value.ToLong() : null;
                    })
                };
                val.ListItem.Len = val.ListItem.LongVal.Length;
            }
            else if ( dataType == FormRecordDataType.Number )
            {
                val.NumStep = col.Precision;
                val.ListItem = new FormListItem
                {
                    DataType = FormRecordDataType.Number,
                    NumVal = vals.ConvertAll<object, decimal?>(a => (decimal)a)
                };
                val.ListItem.Len = val.ListItem.NumVal.Length;
            }
            else if ( dataType == FormRecordDataType.Bool )
            {
                val.ListItem = new FormListItem
                {
                    DataType = FormRecordDataType.Bool,
                    BoolVal = vals.ConvertAll<object, bool?>(a => (bool)a)
                };
                val.ListItem.Len = val.ListItem.BoolVal.Length;
            }
            else
            {
                val.ListItem = new FormListItem
                {
                    DataType = FormRecordDataType.String,
                    StrVal = vals.ConvertAll<object, string>(a => (string)a)
                };
                val.ListItem.Len = val.ListItem.StrVal.Length;
            }
            if ( col.ColumnSet != null && col.FuncType == PageFuncType.None )
            {
                if ( dataType == FormRecordDataType.Bool )
                {
                    val.ActivateText = col.ColumnSet.TryGetValue("ActiveText", out object t) ? t.ToString() : null;
                    val.InactiveText = col.ColumnSet.TryGetValue("InactiveText", out t) ? t.ToString() : null;
                }
                else if ( val.FuncType == DataFuncType.选项值 && col.ColumnSet.TryGetValue("Items", out object obj) && obj != null )
                {
                    IList list = obj as IList;
                    val.Items = new Dictionary<string, string>();
                    foreach ( IDictionary<string, object> i in list )
                    {
                        object k = i["value"];
                        val.Items.Add(Convert.ToString(i["text"]), k == null ? null : Convert.ToString(k));
                    }
                }
                else if ( val.FuncType == DataFuncType.上传的附件 && col.ColumnSet.TryGetValue("DirKey", out obj) && obj != null )
                {
                    val.DirKey = Convert.ToString(obj);
                }
            }
            return val;
        }
        private FormVal _GetRowList ( FormViewColDto col, string tableName )
        {
            FormVal val = new FormVal
            {
                DataType = FormRecordDataType.ListItem,
                IsNull = true,
                FuncType = col.ColFuncType.ToDataFuncType(),
                DicId = col.DictId
            };
            FormListItem list = new FormListItem
            {
                DataType = col.GetDataType()
            };
            if ( list.DataType == FormRecordDataType.Array )
            {
                string[] vals = this._Record.Gets<string>(tableName, col.Alias);
                if ( vals.IsNull() )
                {
                    return val;
                }
                list.Vals = vals.ConvertAll(a => a.SplitDel());
                list.Len = vals.Length;
            }
            else if ( list.DataType == FormRecordDataType.Long || list.DataType == FormRecordDataType.Time )
            {
                list.LongVal = this._Record.Gets<long?>(tableName, col.Alias);
                if ( list.LongVal.IsNull() )
                {
                    return val;
                }
                list.Len = list.LongVal.Length;
            }
            else if ( list.DataType == FormRecordDataType.DateTime ||
                list.DataType == FormRecordDataType.Date )
            {
                DateTime?[] times = this._Record.Gets<DateTime?>(tableName, col.Alias);
                if ( times.IsNull() )
                {
                    return val;
                }
                list.LongVal = times.ConvertAll<DateTime?, long?>(a => a.HasValue ? a.Value.ToLong() : null);
                list.Len = times.Length;
            }
            else if ( list.DataType == FormRecordDataType.Number )
            {
                val.NumStep = col.Precision;
                list.NumVal = this._Record.Gets<decimal?>(tableName, col.Alias);
                if ( list.NumVal.IsNull() )
                {
                    return val;
                }
                list.Len = list.NumVal.Length;
            }
            else if ( list.DataType == FormRecordDataType.Bool )
            {
                list.BoolVal = this._Record.Gets<bool?>(tableName, col.Alias);
                if ( list.BoolVal.IsNull() )
                {
                    return val;
                }
                list.Len = list.BoolVal.Length;
            }
            else
            {
                list.StrVal = this._Record.Gets<string>(tableName, col.Alias);
                if ( list.StrVal.IsNull() )
                {
                    return val;
                }
                list.Len = list.StrVal.Length;
            }
            if ( col.ColumnSet != null && col.FuncType == PageFuncType.None )
            {
                if ( list.DataType == FormRecordDataType.Bool )
                {
                    val.ActivateText = col.ColumnSet.TryGetValue("ActiveText", out object t) ? t.ToString() : null;
                    val.InactiveText = col.ColumnSet.TryGetValue("InactiveText", out t) ? t.ToString() : null;
                }
                else if ( val.FuncType == DataFuncType.选项值 && col.ColumnSet.TryGetValue("Items", out object obj) && obj != null )
                {
                    IList t = obj as IList;
                    val.Items = new Dictionary<string, string>();
                    val.FuncType = DataFuncType.选项值;
                    foreach ( IDictionary<string, object> i in t )
                    {
                        object k = i["value"];
                        val.Items.Add(Convert.ToString(i["text"]), k == null ? null : Convert.ToString(k));
                    }
                }
                else if ( val.FuncType == DataFuncType.上传的附件 && col.ColumnSet.TryGetValue("DirKey", out obj) && obj != null )
                {
                    val.DirKey = Convert.ToString(obj);
                }
            }
            val.ListItem = list;
            val.IsNull = false;
            return val;
        }
        public Dictionary<long, FormVal> GetValues ( FormBase form, FormValsGetArg arg )
        {
            Dictionary<long, FormVal> vals = new Dictionary<long, FormVal>();
            this.LoadValues(form, arg.LinkPK, arg.LinkType, arg.Column, vals);
            return vals;
        }

        public void LoadValues ( FormBase form, long lnkPk, string linkType, KeyValuePair<long, string>[] column, Dictionary<long, FormVal> vals )
        {
            FormViewColDto[] selects = this._ViewCol.Gets<FormViewColDto>(column.ConvertAll(a => a.Key));
            if ( selects.IsNull() )
            {
                return;
            }
            else if ( this._ViewCol.CheckIsExists(form.Id, _Cols) )
            {
                dynamic value = this._Record.Get(form.TableName, linkType, lnkPk, selects.ConvertAll(c => c.Alias));
                selects.ForEach(c =>
                {
                    FormVal val = this._Format(value, c);
                    vals.Add(c.Id, val);
                });
            }
            else
            {
                ExpandoObject[] items = this._Record.Gets(form.TableName, selects.ConvertAll(c => c.Alias));
                selects.ForEach(c =>
                {
                    object[] t = items.ConvertAll(a =>
                    {
                        IDictionary<string, object> dic = a;
                        return dic[c.Alias];
                    });
                    FormVal val = this._Format(t, c);
                    vals.Add(c.Id, val);
                });
            }
        }
    }
}
